﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace THenu.Reflection
{
    /// <summary>
    /// 类型反射的工具
    /// </summary>
    public class RefTool
    {
        /// <summary>
        /// 获取表达式描述的成员
        /// </summary>
        /// <typeparam name="T">
        /// 成员所属类型
        /// </typeparam>
        /// <param name="p_expr">描述成员的表达式</param>
        /// <returns>返回表达式描述的成员</returns>
        public static MemberInfo GetMemberInfo<T>(Expression<Func<T, object>> p_expr)
        {
            return p_expr.Body.GetMemberInfo();
        }

        /// <summary>
        /// 获取表达式描述的字段
        /// </summary>
        /// <typeparam name="T">
        /// 字段成员所属类型
        /// </typeparam>
        /// <param name="p_expr">描述字段的表达式</param>
        /// <returns>返回表达式描述的字段</returns>
        public static FieldInfo GetFieldInfo<T>(Expression<Func<T, object>> p_expr)
        {
            return RefExpression.GetFieldInfo(p_expr.Body);
        }

        /// <summary>
        /// 获取表示式描述的属性
        /// </summary>
        /// <typeparam name="T">
        /// 属性成员所属类型
        /// </typeparam>
        /// <param name="p_expr">描述属性的表达式</param>
        /// <returns>返回表达式定义的属性</returns>
        public static PropertyInfo GetPropertyInfo<T>(Expression<Func<T, object>> p_expr)
        {
            return RefExpression.GetPropertyInfo(p_expr.Body);
        }
    }
    /// <summary>
    /// 表达式扩展类
    /// </summary>
    public static class RefExpression
    {
        /// <summary>
        /// 通过表达式获取成员信息,成员的描述可以包含一个可以转换的一元表达式中
        /// </summary>
        /// <param name="p_body">
        /// 用于计算的成员表达式
        /// </param>
        /// <returns>
        /// 返回表达式描述的字段或者属性
        /// </returns>
        public static MemberInfo GetMemberInfo(this Expression p_body)
        {
            MemberExpression memberExpr = p_body as MemberExpression;

            if (p_body is UnaryExpression)
            {
                var unaryBody = p_body as UnaryExpression;
                if (unaryBody.NodeType != ExpressionType.Convert &&
                    unaryBody.NodeType != ExpressionType.ConvertChecked)
                    throw new ArgumentException("A Non-Convert Unary Expression was found.");

                memberExpr = unaryBody.Operand as MemberExpression;
                if (memberExpr == null)
                    throw new ArgumentException("The target of the Convert operation was not a MemberExpression.");
            }
            else if (memberExpr == null)
            {
                throw new ArgumentException("The Expression must identify a single member.");
            }

            var member = memberExpr.Member;
            if (!(member is FieldInfo || member is PropertyInfo))
                throw new ArgumentException("The member specified was not a Field or Property: " + member.GetType());

            return memberExpr.Member;
        }
        /// <summary>
        /// 封装 GetMemberInfo 方法返回一个字段
        /// </summary>
        /// <param name="p_body">描述字段的表达式</param>
        /// <returns>返回描述的字段</returns>
        public static FieldInfo GetFieldInfo(this Expression p_body)
        {
            var member = GetMemberInfo(p_body);
            if (!(member is FieldInfo))
                throw new ArgumentException("The specified member is not a Field: " + member.GetType());

            return member as FieldInfo;
        }

        /// <summary>
        /// 封装 GetMemberInfo 方法返回一个属性
        /// </summary>
        /// <param name="p_body">描述属性的表达式</param>
        /// <returns>返回描述的属性</returns>
        public static PropertyInfo GetPropertyInfo(this Expression p_body)
        {
            var member = GetMemberInfo(p_body);
            if (!(member is PropertyInfo))
                throw new ArgumentException("The specified member is not a Property: " + member.GetType());

            return member as PropertyInfo;
        }

    }

}
